package com.gopay.scheduler.shedulerx.rdb;

import com.gopay.scheduler.shedulerx.event.ProcessorJobEvent;
import com.gopay.scheduler.shedulerx.event.SchedulerEvent;
import com.gopay.scheduler.shedulerx.event.TriggerMisfireEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.sql.*;

/**
 * @author 19371
 */
public class JobEventTracerRepository extends RdbConfigConstants implements JobRepository {
     private final static Logger LOGGER = LoggerFactory.getLogger(JobEventTracerRepository.class);

    private static JobEventTracerRepository repository = new JobEventTracerRepository();

    private JobEventTracerRepository() {
    }

    public static JobEventTracerRepository getSingle(){
        return repository;
    }

    public void insertMisfire(TriggerMisfireEvent event) {
        String sql = "INSERT INTO `" + SCHEDULER_MISFIRE_RECORD + "` (`app_name`,`job_name`, `event_type`, `trigger_state`, `create_time`,`region`,`decription`) "
                + "VALUES (?, ?, ?, ?, ?,?,?);";
        try (
                Connection conn = dataSource().getConnection();
                PreparedStatement preparedStatement = conn.prepareStatement(sql)) {
            preparedStatement.setString(1,event.getAppName());
            preparedStatement.setString(2, event.getJobName());
            preparedStatement.setString(3, event.getEventType());
            preparedStatement.setString(4, event.getTriggerState());
            preparedStatement.setTimestamp(5, new Timestamp(System.currentTimeMillis()));
            preparedStatement.setString(6, event.getRegion());
            preparedStatement.setString(7, event.getDecription());
            preparedStatement.execute();
        } catch (final SQLException ex) {
            errorLog(LOGGER," insertMisfire event fail，the JobName = {%s}",event.getJobName(),ex);
        }
    }

    public void insertTrace(ProcessorJobEvent processorJobEvent) {
        Integer recordId = checkRecordExist(processorJobEvent.getJobUid());
        if(recordId != null && recordId > 0){
            processorJobEvent.setRecordId(recordId);
            updateTrace(processorJobEvent);
            return;
        }
        String sql = "INSERT INTO `" + SCHEDULER_EVENT_RECORD + "` (`app_name`,`job_name`, `scheduler_stat`, `start_time`, `create_time`, `update_time`, `job_uid`,`region`,`decription`) "
                + "VALUES (?, ?, ?, ?, ?, ?, ?,?,?);";
        try (
                Connection conn = dataSource().getConnection();
                PreparedStatement preparedStatement = conn.prepareStatement(sql)) {
            preparedStatement.setString(1, processorJobEvent.getAppName());
            preparedStatement.setString(2, processorJobEvent.getJobName());
            preparedStatement.setString(3, processorJobEvent.getSchedulerState());
            preparedStatement.setString(4, processorJobEvent.getStartTime());
            preparedStatement.setTimestamp(5, new Timestamp(System.currentTimeMillis()));
            preparedStatement.setTimestamp(6, new Timestamp(System.currentTimeMillis()));
            preparedStatement.setString(7,  processorJobEvent.getJobUid());
            preparedStatement.setString(8,  processorJobEvent.getRegion());
            preparedStatement.setString(9,  processorJobEvent.getDecription());
            preparedStatement.execute();
        } catch (final SQLException ex) {
            errorLog(LOGGER," insertTrace event fail，the JobName = {%s}",processorJobEvent.getJobName(),ex);
        }
    }

    private void updateTrace(ProcessorJobEvent processorJobEvent) {
        String sql = "UPDATE `" + SCHEDULER_EVENT_RECORD + "` SET `scheduler_stat` = ?, `end_time` = ?, `update_time` = ? ,`error_msg` = ? WHERE record_id = ?";
        try (
                Connection conn = dataSource().getConnection();
                PreparedStatement preparedStatement = conn.prepareStatement(sql)) {
            preparedStatement.setString(1, processorJobEvent.getSchedulerState());
            preparedStatement.setString(2, processorJobEvent.getEndTime());
            preparedStatement.setTimestamp(3, new Timestamp(System.currentTimeMillis()));
            preparedStatement.setString(4, processorJobEvent.getErrorMsg());
            preparedStatement.setInt(5, processorJobEvent.getRecordId());
            if (0 == preparedStatement.executeUpdate()) {
               throw new SQLException();
            }
        } catch (final SQLException ex) {
            errorLog(LOGGER," updateTrace event fail，the JobName = {%s}",processorJobEvent.getJobName(),ex);
        }
    }

    private Integer checkRecordExist(String jobUid) {
        String sql = String.format("SELECT record_id FROM %s where job_uid = '%s' ",SCHEDULER_EVENT_RECORD,jobUid);
        try (
                Connection conn = dataSource().getConnection();
                PreparedStatement preparedStatement = conn.prepareStatement(sql);
                ResultSet resultSet = preparedStatement.executeQuery()
        ) {
            if (resultSet.next()) {
               return resultSet.getInt("record_id");
            }
        } catch (final SQLException ex) {
            errorLog(LOGGER," checkRecordExist event fail，the jobUid = {%s}",jobUid,ex);
        }
        return null;
    }

    public void insertScheduler(SchedulerEvent schedulerEvent) {
        String sql = "INSERT INTO `" + SCHEDULER_OPERATE_RECORD + "` (`app_name`,`job_name`, `operate_type`, `msg`, `create_time`) "
                + "VALUES (?, ?, ?, ?, ?);";
        try (
                Connection conn = dataSource().getConnection();
                PreparedStatement preparedStatement = conn.prepareStatement(sql)) {
            preparedStatement.setString(1,schedulerEvent.getAppName());
            preparedStatement.setString(2, schedulerEvent.getJobName());
            preparedStatement.setString(3, schedulerEvent.getOperateType());
            preparedStatement.setString(4, schedulerEvent.getMsg());
            preparedStatement.setTimestamp(5, new Timestamp(System.currentTimeMillis()));
            preparedStatement.execute();
        } catch (final SQLException ex) {
            errorLog(LOGGER," insertScheduler event fail，the operate_type = {%s}",schedulerEvent.getOperateType()+"{JobName=:"+schedulerEvent.getJobName()+"}",ex);
        }
    }
}
